#include <iostream>

using namespace std;

class Rational {
public:
    Rational(int n, int d) {
        if (d == 0) {
            throw 0;
        }
        this->g = this->gcd(abs(n), abs(d));
        this->number = n / this->g;
        this->denom = d / this->g;
        if (this->number < 0 and this->denom < 0) {
            this->number = abs(this->number);
            this->denom = abs(this->denom);
        }
    }

    explicit Rational(int n) {
        this->number = n;
    }

    Rational operator+(const Rational &p) const {
        Rational temp(this->number * p.denom + p.number * this->denom, this->denom * p.denom);
        return temp;
    }

    Rational operator+(const int p) const {
        Rational temp(this->number + p * this->denom, this->denom);
        return temp;
    }

    Rational operator-(const Rational &p) const {
        Rational temp(this->number * p.denom - p.number * this->denom, this->denom * p.denom);
        return temp;
    }

    Rational operator-(const int p) const {
        Rational temp(this->number - p * this->denom, this->denom);
        return temp;
    }

    Rational operator*(const Rational &p) const {
        Rational temp(this->number * p.number, this->denom * p.denom);
        return temp;
    }

    Rational operator*(const int p) const {
        Rational temp(this->number * p, this->denom);
        return temp;
    }

    Rational operator/(const Rational &p) const {
        Rational temp(this->number * p.denom, this->denom * p.number);
        return temp;
    }

    Rational operator/(const int p) const {
        Rational temp(this->number, this->denom * p);
        return temp;
    }


    string toString() const {
        string res;
        res.append("Rational: (");
        res.append(to_string(number));
        res.append(") / (");
        res.append(to_string(denom));
        res.append(")");
        return res;
    }

private:
    int number;
    int denom = 1;
    int g = 1;

    int gcd(int a, int b) {
        if (b == 0) {
            return a;
        } else {
            return this->gcd(b, a % b);
        }
    }
};


int main() {
    Rational num1(-20);
    cout << num1.toString() << endl;//Rational: (-20) / (1)

    Rational num2(-2, -2);
    cout << num2.toString() << endl;//Rational: (1) / (1)

    Rational a = num1 / num2;
    cout << a.toString() << endl;//Rational: (-20) / (1)

    Rational b = num1 - 3;
    cout << b.toString() << endl;//Rational: (-23) / (1)

     Rational num3(-2, 0);
     cout << num3.toString() << endl;//terminate called after throwing an instance of 'int'

    // ERROR
    // Rational c = 3 + num1;
    // cout << c.toString() << endl;

    return 0;
}
